;;;; bmd-mode.el
;;;; Creates a emacs major mode for use with BMDLang

(defcustom bmd-types 
  '("int" "float" "string" "bool" "array" "void" "enum" "struct" "list" "ref")
  "Types in BMD Lang"
  :type 'list
  :group 'bmd-font-lock)

(defcustom bmd-keywords
  '("include" "remotable" "not" "if" "else" "while" "for"
    "do" "car" "cdr" "trunc" "and" "or" "break" "continue" 
    "return" "template" "state" "stateMachine" "stateTransition")
  "Keywords in BMDLang"
  :type 'list
  :group 'bmd-font-lock)

(defcustom bmd-constants
  '("nil" "true" "false" 
    "transitionPredicates" "transitionTargets"
    "stateMachineInit")
  "Constant literals"
  :type 'list
  :group 'bmd-font-lock)

(defvar bmd-keywords-regexp (regexp-opt bmd-keywords 'words))
(defvar bmd-types-regexp (regexp-opt bmd-types 'words))
(defvar bmd-constants-regexp (regexp-opt bmd-constants 'words))

(setq bmd-font-lock-keywords
      `(,bmd-keywords-regexp
	(,bmd-types-regexp . font-lock-type-face)
	(,bmd-constants-regexp . font-lock-constant-face)

	;; function declarations
	("\\(\\<\\w+\\>\\)\\s *\\(\\<\\w+\\>\\)[[:space:]]*(" 
	 2 font-lock-function-name-face)

	;; variable declarations
	("\\(\\<\\w+\\>\\)\\s *\\(\\<\\w+\\>\\)" 2 font-lock-variable-name-face)
	("\\(\\<\\w+\\>\\)\\s *\\(\\<\\w+\\>\\)" 1 font-lock-type-face)

	;; the variable declaration syntax buffer includes "return x(...)", which
	;; we don't want
	("return\s *\\(\\<\\w+\\>\\)" 1 nil t)

	;; give syntax highlighting to function names in state machine
	("\\(\\<\\w+\\>\\)\s *:[^:]" 1 font-lock-constant-face)

	;; no syntax highlighting on lines in the state machine
	("\\<\\w+\\>:[^:]\\(.*\\)" 1 nil t)

	;; compound types
	("\\(\\<\\w+\\>\\) list" 1 font-lock-type-face)
	("\\(\\<\\w+\\>\\) array" 1 font-lock-type-face)
	("list \\(\\<\\w+\\>\\)" 1 font-lock-variable-name-face)
	
	; array variables
	("\\[.*\\]\\s *\\(\\<\\w+\\>\\)" 1 font-lock-variable-name-face)))

;; couple of syntax table alterations
(defvar bmd-syntax-table (copy-syntax-table c++-mode-syntax-table)
  "Syntax table for BMDLang")

(modify-syntax-entry ?\: "." bmd-syntax-table)
(modify-syntax-entry ?\_ "w" bmd-syntax-table)

(define-derived-mode bmd-mode c++-mode "bmd"
  "Major mode for editing BMDLang, a language created for our cs136 project"
  (setq font-lock-defaults '((bmd-font-lock-keywords) nil nil))
  (set-syntax-table bmd-syntax-table))
	   
(provide 'bmd-mode)
